package top.ahzy.seobench.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import top.ahzy.seobench.config.async.TaskDecoratorForMdc;
import top.ahzy.seobench.config.async.ThreadPoolMdcExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 启用异步任务
 * @author ahzy
 */
@EnableAsync
@Configuration
public class AsyncConfig {
    /**
     * IO密集型任务  = 一般为2*CPU核心数（常出现于线程中：数据库数据交互、文件上传下载、网络数据传输等等）
     * CPU密集型任务 = 一般为CPU核心数+1（常出现于线程中：复杂算法）
     * 混合型任务  = 视机器配置和复杂度自测而定
     */
    public static final int cpuNum = Runtime.getRuntime().availableProcessors();

    /**
     * 声明一个线程池(并指定线程池的名字)
     * @return
     */
    @Bean
    public Executor asyncExecutor() {
        ThreadPoolMdcExecutor executor = new ThreadPoolMdcExecutor();
        //核心线程数 cpuNum：线程池创建时候初始化的线程数
        executor.setCorePoolSize(cpuNum);
        //核心线程数 cpuNum：线程池创建时候初始化的线程数
        executor.setMaxPoolSize(cpuNum * 2);
        //缓冲队列500：用来缓冲执行任务的队列
        executor.setQueueCapacity(500);
        //允许线程的空闲时间60秒：当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setKeepAliveSeconds(60);

        /**
         * 拒绝处理策略
         * CallerRunsPolicy()：交由调用方线程运行，比如 main 线程。
         * AbortPolicy()：直接抛出异常。
         * DiscardPolicy()：直接丢弃。
         * DiscardOldestPolicy()：丢弃队列中最老的任务。
         */
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //调度器shutdown被调用时等待当前被调度的任务完成
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //等待时长
        executor.setAwaitTerminationSeconds(60);
        //线程池名的前缀：设置好了之后可以方便我们定位处理任务所在的线程池
        executor.setThreadNamePrefix("ExecuteAsync-");
        //线程池增强
        executor.setTaskDecorator(new TaskDecoratorForMdc());
        //线程初始化
        executor.initialize();
        return executor;
    }

}
